package org.jarraiders.musiclibrary.server.service;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.jarraiders.musiclibrary.domain.Album;
import org.jarraiders.musiclibrary.server.utils.HibernateUtil;

/**
 * @author AlteroStudio
 */
abstract public class EntityDAOImpl<Entity> implements EntityDAO<Entity> {

	protected static final byte ERROR_MSG = 0;
	protected static final byte DEBUG_MSG = 1;

	private final Class<Entity> entityClass;
	private Log logger;

	public EntityDAOImpl(Class<Entity> entityClass) {
		this.entityClass = entityClass;
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Entity> getAllEntities() {
		logMessage(DEBUG_MSG, "Getting all Entities");

		Session session = null;
		Transaction tx = null;
		List<Entity> list = new ArrayList<Entity>();

		try {
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();

			list = session.createCriteria(entityClass).list();

			tx.commit();

		} catch (RuntimeException e) {
			if (tx != null && tx.isActive()) {
				try {
					tx.rollback();
				} catch (HibernateException he) {
					logMessage(ERROR_MSG,
							he.getMessage() + ":\n" + e.toString());
					throw new HibernateException(he);
				}
			}
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}

		return list;
	}

	@Override
	public boolean addNewEntity(Entity entity) {

		logMessage(DEBUG_MSG, "Adding new Entity");

		boolean result = false;

		Session session = null;
		Transaction tx = null;

		try {
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();

			session.save(entity);

			tx.commit();

			result = true;

		} catch (RuntimeException e) {
			if (tx != null && tx.isActive()) {
				try {
					tx.rollback();
				} catch (HibernateException he) {
					logMessage(ERROR_MSG,
							he.getMessage() + ":\n" + e.toString());
					throw new HibernateException(he);
				}
			}
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}

		return result;
	}

	@Override
	public Entity getEntityById(String id) {
		Entity entity;

		entity = getEntityById(UUID.fromString(id));

		return entity;
	}

	@Override
	@SuppressWarnings("unchecked")
	public Entity getEntityById(UUID id) {

		logMessage(DEBUG_MSG, "Getting Entity by ID");

		Session session = null;
		Transaction tx = null;
		Entity entity = null;

		try {
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();

			entity = (Entity) session.get(entityClass, id);

			tx.commit();

		} catch (RuntimeException e) {
			if (tx != null && tx.isActive()) {
				try {
					tx.rollback();
				} catch (HibernateException he) {
					logMessage(ERROR_MSG,
							he.getMessage() + ":\n" + e.toString());
					throw new HibernateException(he);
				}
			}
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}

		return entity;
	}

	@Override
	public boolean updateEntity(Entity entity) {

		logMessage(DEBUG_MSG, "Updating Entity");

		boolean result = false;

		Session session = null;
		Transaction tx = null;

		try {
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();

			session.update(entity);

			tx.commit();

			result = true;

		} catch (RuntimeException e) {
			if (tx != null && tx.isActive()) {
				try {
					tx.rollback();
				} catch (HibernateException he) {
					logMessage(ERROR_MSG,
							he.getMessage() + ":\n" + e.toString());
					throw new HibernateException(he);
				}
			}
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}

		return result;
	}

	@Override
	public boolean deleteEntity(Entity entity) {

		logMessage(DEBUG_MSG, "Deleting new Entity");

		boolean result = false;

		Session session = null;
		Transaction tx = null;

		try {
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();
			
			session.delete(entity);

			tx.commit();

			result = true;

		} catch (RuntimeException e) {
			if (tx != null && tx.isActive()) {
				try {
					tx.rollback();
				} catch (HibernateException he) {
					logMessage(ERROR_MSG,
							he.getMessage() + ":\n" + e.toString());
					throw new HibernateException(he);
				}
			}
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}

		return result;
	}

	
	public abstract List<Entity> searchEntity(String searchText);
	public void setLoggerTarget(String targetName) {
		logger = LogFactory.getLog(targetName);
	}

	@Override
	public void logMessage(byte messageType, String message) {
		if (logger != null) {
			switch (messageType) {
			case EntityDAOImpl.ERROR_MSG:
				logger.error(message);
				break;
			case EntityDAOImpl.DEBUG_MSG:
				logger.debug(message);
				break;
			}
		}
	}
}
